﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NetworkCrashSimulator.Core
{
    public enum ActionError : short
    {
        NoError = 0,
        UnableToCrash = 1,
        UnableToRestore = 2,
        UnableToList = 3,
        AdapterNotFound = 4
    }

    public class Actions
    {
        /// <summary>
        /// Generate a console line following the application template.
        /// </summary>
        /// <param name="message">Message to show on the console line.</param>
        /// <remarks>Date and time will appear in the console line.</remarks>
        internal static void GenerateConsoleLine(string message)
        {
            GenerateConsoleLine(message, true);
        }

        /// <summary>
        /// Generate a console line following the application template.
        /// </summary>
        /// <param name="message">Message to show on the console line.</param>
        /// <param name="addDateTime">Date time should be added to the console line?</param>
        internal static void GenerateConsoleLine(string message, bool addDateTime)
        {
            if (addDateTime)
            {
                message = string.Format("[{0}] {1}", DateTime.Now.ToString(), message);
            }

            Console.WriteLine(message);
        }


        /// <summary>
        /// Crash a specific network adapter.
        /// </summary>
        /// <param name="adapterName">Name of the network adapter.</param>
        /// <returns>Error for the action.</returns>
        public static ActionError CrashAdapter(string adapterName)
        {
            ActionError error = ActionError.NoError;

            Core.NetworkAdapterConfiguration.NetworkAdapterConfigurationCollection networkAdapters = Core.NetworkAdapterConfiguration.GetInstances("Description = '" + adapterName + "'");

            if (networkAdapters.Count == 1)
            {
                foreach (Core.NetworkAdapterConfiguration networkAdapter in networkAdapters)
                {
                    CrashAdapter(networkAdapter);
                }
            }
            else
            {
                error = ActionError.AdapterNotFound;
                GenerateConsoleLine("Network adapter not found.");
            }

            return error;
        }

        /// <summary>
        /// Crash a specific network adapter.
        /// </summary>
        /// <param name="networkAdapter">Network adapter object.</param>
        /// <returns>Error for the action.</returns>
        private static ActionError CrashAdapter(Core.NetworkAdapterConfiguration networkAdapter)
        {
            ActionError error = ActionError.NoError;

            try
            {
                GenerateConsoleLine("Trying to crash network adapter " + networkAdapter.Description + ".");
                networkAdapter.ReleaseDHCPLease();
                GenerateConsoleLine("Network adapter crashed successfully.");
            }
            catch (Exception ex)
            {
                error = ActionError.UnableToCrash;
                GenerateConsoleLine("Problems crashing the network adapter: " + ex.Message);
            }

            return error;
        }

        /// <summary>
        /// Repair a specific network adapter.
        /// </summary>
        /// <param name="adapterName">Name of the network adapter.</param>
        /// <returns>Error for the action.</returns>
        public static ActionError RepairAdapter(string adapterName)
        {
            ActionError error = ActionError.NoError;

            Core.NetworkAdapterConfiguration.NetworkAdapterConfigurationCollection networkAdapters = Core.NetworkAdapterConfiguration.GetInstances("Description = '" + adapterName + "'");

            if (networkAdapters.Count == 1)
            {
                foreach (Core.NetworkAdapterConfiguration networkAdapter in networkAdapters)
                {
                    RepairAdapter(networkAdapter);
                }
            }
            else
            {
                error = ActionError.AdapterNotFound;
                GenerateConsoleLine("Network adapter not found.");
            }

            return error;
        }

        /// <summary>
        /// Repair a specific network adapter.
        /// </summary>
        /// <param name="networkAdapter">Network adapter object.</param>
        /// <returns>Error for the action.</returns>
        private static ActionError RepairAdapter(Core.NetworkAdapterConfiguration networkAdapter)
        {
            ActionError error = ActionError.NoError;

            try
            {
                GenerateConsoleLine("Trying to repair network adapter " + networkAdapter.Description + ".");
                networkAdapter.RenewDHCPLease();
                GenerateConsoleLine("Network adapter repaired successfully.");
            }
            catch (Exception ex)
            {
                error = ActionError.UnableToRestore;
                GenerateConsoleLine("Problems repairing the network adapter: " + ex.Message);
            }

            return error;
        }

        /// <summary>
        /// List available network adapter.
        /// </summary>
        /// <returns>Error for the action.</returns>
        /// <remarks>Only works on the console.</remarks>
        //TODO: Change "ListAdapters()" method so it can be reused in a future GUI.
        public static ActionError ListAdapters()
        {
            ActionError error = ActionError.NoError;

            try
            {
                Core.NetworkAdapterConfiguration.NetworkAdapterConfigurationCollection networkAdaptersConfigurations = Core.NetworkAdapterConfiguration.GetInstances();

                if (networkAdaptersConfigurations.Count > 0)
                {
                    GenerateConsoleLine("Listing available network adapters:", false);
                    short counting = 1;
                    foreach (Core.NetworkAdapterConfiguration networkAdapterConfiguration in networkAdaptersConfigurations)
                    {
                        GenerateConsoleLine("   " + counting.ToString() + ". " + networkAdapterConfiguration.Description, false);
                        counting++;
                    }
                    GenerateConsoleLine(String.Empty, false);
                    GenerateConsoleLine(String.Empty, false);
                }
                else
                {
                    GenerateConsoleLine("No network adapter available.");
                }

            }
            catch (Exception ex)
            {
                error = ActionError.UnableToRestore;
                GenerateConsoleLine("Problems listing network adapters: " + ex.Message);
            }

            return error;
        }
    }
}
